package com.jt.shiro;

import com.jt.base.utils.Constant;
import com.jt.permission.model.Menu;
import com.jt.permission.model.Role;
import com.jt.permission.model.User;
import com.jt.permission.service.MenuService;
import com.jt.permission.service.RoleService;
import com.jt.permission.service.UserService;
import com.jt.permission.helper.MenuHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import java.util.*;

/** 认证 */
@Component
public class UserRealm extends AuthorizingRealm {
  @Autowired
  private UserService userService;
  @Autowired
  private MenuService menuService;
  @Autowired
  private RoleService roleService;
  @Autowired
  private MenuHelper menuHelper;
  /** 授权(验证权限时调用) */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    User user = (User) principals.getPrimaryPrincipal();
    // 用户权限列表
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    info.setStringPermissions(user.getPermissionSet());
    info.setRoles(user.getRoleSet());
    return info;
  }

  /** 认证(登录时调用) */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
      throws AuthenticationException {
    UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

    // 查询用户信息
    Example example = new Example(User.class);
    example.createCriteria().andEqualTo("username", token.getUsername());
    User user = null;
    List<User> list = userService.selectListByExample(example);
    if (list != null && list.size() > 0) {
      user = list.get(0);
    }
    // 账号不存在
    if (user == null) {
      throw new UnknownAccountException("账号或密码不正确");
    }

    // 账号锁定
    if (user.getStatus() == Constant.SYS_USER_STATUS_FREEZE) {
      throw new LockedAccountException("账号已被锁定,请联系管理员");
    }
    List<Role> roles = new ArrayList<>() ;
    List<Menu> menus =new ArrayList<>();
    if(user.getUserId()==Constant.SUPER_ADMIN){//管理员查询所有角色和菜单
      roles =roleService.selectAll();
      menus = menuService.selectAll();
    }else{
      roles=roleService.queryAllRolles(user.getUserId());
      List<Long> roleIds = new ArrayList<>();
      for (Role role : roles) {
        roleIds.add(role.getRoleId());
      }
      if(roleIds!=null&&roleIds.size()>0){
        menus = menuService.queryAllMenus(roleIds);
      }
    }
    //填充用户权限
   Set<String> permissionSet = new HashSet<>();
    if(menus!=null){
      for (Menu sysMenu : menus) {
        if(StringUtils.isNotBlank(sysMenu.getPerms())){
          permissionSet.addAll(Arrays.asList(sysMenu.getPerms().trim().split(",")));
        }
      }
    }
    user.setPermissionSet(permissionSet);
    //填充用户角色
    Set<String> roleSet = new HashSet<>();
    if(roles!=null){
      for (Role sysRole : roles) {
        if(StringUtils.isNotBlank(sysRole.getRoleName())){
          roleSet.add(sysRole.getRoleName());
        }
      }
    }
    user.setRoleSet(roleSet);
    user.setRoles(roles);
    user.setMenus(menuHelper.treeMenu(menus,false));

    SimpleAuthenticationInfo info =
        new SimpleAuthenticationInfo(
            user, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName());
    return info;
  }

  @Override
  public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
    HashedCredentialsMatcher shaCredentialsMatcher = new HashedCredentialsMatcher();
    shaCredentialsMatcher.setHashAlgorithmName(ShiroUtils.hashAlgorithmName);
    shaCredentialsMatcher.setHashIterations(ShiroUtils.hashIterations);
    shaCredentialsMatcher.setStoredCredentialsHexEncoded(true);
    super.setCredentialsMatcher(shaCredentialsMatcher);
  }
}
